home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 79 / maccd 79.iso / multimedial / GL Tron / Source / gltron / menu.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-20  |  15.3 KB  |  581 lines  |  [TEXT/CWIE]

  1. #include "gltron.h"
  2. #include <string.h>
  3.  
  4. Menu *pCurrent = 0;
  5.  
  6. #define MENU_BUFSIZE 100
  7.  
  8.  
  9. // static char *speed_list[] = {  "boring", "normal", "fast", "crazy", "custom", NULL };
  10. static char *speed_list[] = {  "boring", "normal", "fast", "crazy", NULL };
  11. static char *player_list[] = { "human", "computer", "none", NULL };
  12. static char *arena_list[] = { "tiny", "medium", "big", "vast", "extreme", NULL };
  13. static char *lod_list[] = { "normal", "lower", "ugly", NULL };
  14. static char *ai_list[] = { "dumb", "normal", "strong", "the MCP himself", NULL };
  15. static char *filter_list[] = { "bilinear", "trilinear", NULL };
  16. static char *camera_list[] = { "circling", "behind", "cockpit", "mouse", NULL };
  17. static char *viewports_list[] = { "single", "split", "4 player", NULL };
  18.  
  19. static char **clists[] = { speed_list, player_list, arena_list, lod_list,
  20.                ai_list, filter_list, camera_list, viewports_list,
  21.                NULL 
  22. };
  23.  
  24. void changeAction(char *name) {
  25. #ifdef SOUND
  26.   if(strstr(name, "playMusic") == name) {
  27.     if(game->settings->playMusic == 0)
  28.       stopSound();
  29.     else if(game->settings->soundIndex >= 0)
  30.       playSound();
  31.   } else if(strstr(name, "musicVolume") == name) {
  32.     setMusicVolume(game->settings->musicVolume);
  33.   } else if(strstr(name, "fxVolume") == name) {
  34.     setFxVolume(game->settings->fxVolume);
  35.     playMenuFX(fx_highlight);
  36.   } else if(strstr(name, "song") == name) {
  37.     if(game->settings->soundIndex != -1) {
  38.       char *tmp;
  39.       char *path;
  40.       list *p;
  41.       int c;
  42.  
  43.       c = 0;
  44.       for(p = game->settings->soundList; p->next != NULL; p = p->next) {
  45.     if(c == game->settings->soundIndex)
  46.       break;
  47.     c++;
  48.       }      
  49.       if(c == game->settings->soundIndex) {
  50.     path = getFullPath(MUSIC_DIR);
  51.     tmp = malloc(strlen(path) + 1 + /* seperator */
  52.              strlen((char*) p->data) + 1);
  53.     sprintf(tmp, "%s%c%s", path, SEPERATOR, 
  54.         (char*) p->data);
  55.     fprintf(stderr, "loading song %s\n", tmp);
  56.  
  57.     if(game->settings->playMusic)
  58.       stopSound();
  59.     loadSound(tmp);
  60.     free(tmp);
  61.     if(game->settings->playMusic)
  62.       playSound();
  63.       }
  64.     } else {
  65.       if(game->settings->playMusic)
  66.     stopSound();
  67.     }
  68.   }
  69. #endif
  70.   if(strstr(name, "use_mipmaps") == name ||
  71.      strstr(name, "mipmap_filter") == name) {
  72.     deleteFonts();
  73.     deleteTextures(game->screen);
  74.     initFonts();
  75.     initTexture(game->screen);
  76.   }
  77.   else if(strstr(name, "game_speed") == name) {
  78.     game->settings->current_speed = 
  79.       default_speeds[ game->settings->game_speed ];
  80.     initData();
  81.   } 
  82.   else if(strstr(name, "arena_size") == name) {
  83.     game->settings->grid_size = 
  84.       default_arena_sizes[ game->settings->arena_size ];
  85.     initData();
  86.   } 
  87.   else if(strstr(name, "display_type") == name) {
  88.     changeDisplay();
  89.   } 
  90.   else if(strstr(name, "resetScores") == name)
  91.     resetScores();
  92.  
  93.   else if(strstr(name, "ai_player") == name) {
  94.     int c;
  95.     int *v;
  96.  
  97.     /* printf("changing AI status\n"); */
  98.     c = name[9] - '0';
  99.     v = getVi(name);
  100.     game->player[c - 1].ai->active = *v;
  101.     /* printf("changed AI status for player %c\n", c + '0'); */
  102.   } 
  103.   else if(strstr(name, "windowMode") == name) {
  104.     initGameScreen();
  105.     shutdownDisplay(game->screen);
  106.     setupDisplay(game->screen);
  107.  
  108.     updateCallbacks();
  109.     changeDisplay();
  110.   } else if(strstr(name, "artpack") == name) {
  111.     reloadArt();
  112.   } else if(strstr(name, "mouse_warp") == name) {
  113.     if(game->settings->mouse_warp == 1)
  114.       SystemGrabInput();
  115.     else
  116.       if(game->settings->windowMode == 1) SystemUngrabInput();
  117.   }
  118.  
  119. }
  120.  
  121. void menuAction(Menu *activated, int type) {
  122.   int x, y;
  123.   char c;
  124.   int *piValue;
  125.   if(activated->nEntries > 0) {
  126.     pCurrent = activated;
  127.     pCurrent->iHighlight = 0;
  128.   } else if (type == MENU_ACTION) {
  129.     switch(activated->szName[1]) { /* second char */
  130.     case 'q': saveSettings(); SystemExit(); break;
  131.     case 'r': 
  132.       initData();
  133.       game2->mode = GAME_SINGLE;
  134.       switchCallbacks(&pauseCallbacks);
  135.       break;
  136.     case 'a': // this menu code is turning uglier and uglier 
  137.       printf("artpack menu chosen\n");
  138.       artpack_index++;
  139.       if(artpack_list[artpack_index] == NULL)
  140.     artpack_index = 0;
  141.       initMenuCaption(activated);
  142.       changeAction(activated->szName + 3);
  143.       break;
  144.     case 'd':
  145.       if(activated->szName[2] == 'p') {
  146.     initData();
  147.     if(startPlaying("demo.txt")) {
  148.       fprintf(stderr, "starting \"play demo\" failed\n");
  149.       break;
  150.     }
  151.     if(readDemoInfo()) {
  152.       fprintf(stderr, "reading demo information failed\n");
  153.       break;
  154.     }
  155.     applyGameInfo();
  156.     game2->mode = GAME_PLAY;
  157.     switchCallbacks(&pauseCallbacks);
  158.       } else if(activated->szName[2] == 'r') {
  159.     initData();
  160.     if(startRecording("demo.txt")) {
  161.       fprintf(stderr, "starting \"record demo\" failed\n");
  162.       break;
  163.     }
  164.     if(writeDemoInfo()) {
  165.       fprintf(stderr, "writing demo information failed\n");
  166.       break;
  167.     }
  168.     game2->mode = GAME_SINGLE_RECORD;
  169.     switchCallbacks(&pauseCallbacks);
  170.       }
  171.       break;
  172.     case 'v':
  173.       sscanf(activated->szName, "%cv%dx%d ", &c, &x, &y);
  174.       game->settings->width = x;
  175.       game->settings->height = y;
  176.  
  177.       initGameScreen();
  178.       shutdownDisplay(game->screen);
  179.       setupDisplay(game->screen);
  180.  
  181.       updateCallbacks();
  182.       changeDisplay();
  183.       break;
  184.     case 'k': {
  185.       int player, turn;
  186.       int i;
  187.       /* TODO: set target key name */
  188.       sscanf(activated->szName + 1, "k_%d_%d ", &player, &turn);
  189.       for(i = 0; i < KEY_ACTIONS_N; i++)
  190.     if(key_actions[i].player == player &&
  191.        key_actions[i].turn == turn) {
  192.       configureKeyEntry = &(key_actions[i].key);
  193.       break;
  194.     }
  195.       configureKeyMenu = activated;
  196.       switchCallbacks(&configureCallbacks);
  197.       break;
  198.     }
  199.     case 't':
  200.       switch(activated->szName[2]) {
  201.       case 'i':
  202.     piValue = getVi(activated->szName + 4);
  203.     if(piValue != NULL) {
  204.       *piValue = (*piValue - 1) * (-1);
  205.       initMenuCaption(activated);
  206.       changeAction(activated->szName + 4);
  207.     }
  208.     break;
  209.       case 'l':
  210.     {
  211.       char buf[64];
  212.       // int max_value;
  213.       int dummy;
  214.       int clist_index;
  215.       
  216.       // sscanf(activated->szName, "stl_%d_%d_%s", &dummy, &max_value, buf);
  217.       sscanf(activated->szName, "stl_%d_%d_%s", &clist_index, &dummy, buf);
  218.       piValue = getVi(buf);
  219.       if(piValue != NULL) {
  220.         (*piValue)++;
  221.         // if(*piValue > max_value) *piValue = 0;
  222.         if(clists[clist_index][*piValue] == NULL) *piValue = 0;
  223.         initMenuCaption(activated);
  224.         changeAction(buf);
  225.         break;
  226.       }
  227.     }
  228.       }
  229.       break;
  230.     case 'p':
  231.       changeAction(activated->szName + 4);
  232.     case 'c':
  233.       chooseCallback(activated->szName + 3);
  234.       break;
  235.     case 'm':
  236.       changeAction(activated->szName + 3);
  237.       break;
  238.     default: printf("got action for menu %s\n", activated->szName); break;
  239.     }
  240.   } else if(type == MENU_LEFT || type == MENU_RIGHT) {
  241.     switch(activated->szName[1]) {
  242.     case 's': 
  243.       {
  244.     float *pfValue;
  245.     float min, max, step;
  246.     char buf[64];
  247.     sscanf(activated->szName, "ssf_%f_%f_%f_%s", &min, &max, &step, buf);
  248.     pfValue = getVf(buf);
  249.     if(pfValue != NULL) {
  250.       *pfValue = (type == MENU_LEFT) ? (*pfValue - step) : (*pfValue + step);
  251.       if(*pfValue < min) *pfValue = min;
  252.       if(*pfValue > max) *pfValue = max;
  253.     }
  254.     initMenuCaption(activated);
  255.     changeAction(buf);
  256.     break;
  257.       }
  258.     case 'm':
  259.       switch(type) {
  260.       case MENU_LEFT:
  261.     game->settings->soundIndex--;
  262.     if(game->settings->soundIndex < -1) game->settings->soundIndex = -1;
  263.     break;
  264.       case MENU_RIGHT:
  265.     game->settings->soundIndex++;
  266.     if(game->settings->soundIndex >= game->settings->soundSongCount) 
  267.       game->settings->soundIndex = game->settings->soundSongCount - 1;
  268.     break;
  269.       }
  270.       initMenuCaption(activated);
  271.       break;
  272.     }
  273.   }
  274. }
  275.  
  276. void initMenuCaption(Menu *m) {
  277.   int *piValue;
  278.  
  279.   /* TODO support all kinds of types */
  280.   switch(m->szName[0]) {
  281.   case 's':
  282.     switch(m->szName[1]) {
  283.     case 'a':
  284.       printf("setting artpack menu caption\n");
  285.       sprintf(m->display.szCaption, m->szCapFormat, 
  286.           artpack_list[artpack_index]);
  287.       break;
  288.     case 't':
  289.       switch(m->szName[2]) {
  290.       case 'i':
  291.     /* printf("dealing with %s\n", m->szName); */
  292.     piValue = getVi(m->szName + 4);
  293.     if(piValue != NULL) {
  294.       if(*piValue == 0) sprintf(m->display.szCaption,
  295.                     m->szCapFormat, "off");
  296.       else sprintf(m->display.szCaption, m->szCapFormat, "on");
  297.       /* printf("changed caption to %s\n", m->display.szCaption); */
  298.     } /* else printf("can't find value for %s\n", m->szName + 4); */
  299.     break;
  300.       case 'l':
  301.     {
  302.       int clist_index;
  303.       int dummy;
  304.       char buf[64];
  305.       sscanf(m->szName, "stl_%d_%d_%s ", &clist_index, &dummy, buf);
  306.       piValue = getVi(buf);
  307.       /* TODO: bounds checking */
  308.       sprintf(m->display.szCaption, m->szCapFormat,
  309.           (clists[clist_index])[*piValue]);
  310.       break;
  311.     }
  312.       } /* end szName[2] */
  313.       break;
  314.     case 'k': 
  315.       { /* set key name in menu */
  316.       int player, turn;
  317.       int i;
  318.       int key;
  319.       char *caption = NULL;
  320.       sscanf(m->szName + 1, "k_%d_%d ", &player, &turn);
  321.       for(i = 0; i < KEY_ACTIONS_N; i++)
  322.     if(key_actions[i].player == player &&
  323.        key_actions[i].turn == turn) {
  324.       key = key_actions[i].key;
  325.       caption = SystemGetKeyName(key);
  326.       break;
  327.     }
  328.       sprintf(m->display.szCaption, m->szCapFormat, caption);
  329.       /* free(caption); */
  330.       break;
  331.       }
  332.     case 's': /* slider */
  333.       switch(m->szName[2]) {
  334.     case 'f':
  335.       {
  336.         char buf[64];
  337.         float *pfValue;
  338.         sscanf(m->szName, "ssf_%*f_%*f_%*f_%s ", buf);
  339.         pfValue = getVf(buf);
  340.         if(pfValue != NULL) {
  341.           sprintf(m->display.szCaption, m->szCapFormat, *pfValue * 100);
  342.         }
  343.         break;
  344.       }
  345.       }
  346.       break;
  347.     case 'm': /* song */
  348.       {
  349.     list *p;
  350.     int c = 0;
  351.     for(p = game->settings->soundList; p->next != NULL; p = p->next) {
  352.       if(c == game->settings->soundIndex)
  353.         sprintf(m->display.szCaption, m->szCapFormat, 
  354.             (char*) p->data + strlen(SONG_PREFIX));
  355.       c++;
  356.     }
  357.     if(game->settings->soundIndex == -1)
  358.       sprintf(m->display.szCaption, m->szCapFormat, "none");
  359.       }
  360.       break;
  361.     }
  362.     break;
  363.   default:
  364.     sprintf(m->display.szCaption, "%s", m->szCapFormat);
  365.     /* printf("using default capformat\n"); */
  366.   }
  367.   /* printf("[menu] cap-format: %s, caption: %s\n", m->szCapFormat,
  368.      m->display.szCaption); */
  369.  
  370. }
  371.  
  372. void getNextLine(char *buf, int bufsize, FILE* f) {
  373.   fgets(buf, bufsize, f);
  374.   while((buf[0] == '\n' || buf[0] == '#') &&
  375.     fgets(buf, bufsize, f));
  376. }
  377.  
  378. /* loadMenu returns the current Menu (sub-) tree */
  379.  
  380. Menu* loadMenu(FILE* f, char* buf, Menu* parent, int level) {
  381.   Menu* m;
  382.   int i;
  383.  
  384.  
  385.   if(level > 4) {
  386.     printf("recursing level > 4 - aborting\n");
  387.     exit(1);
  388.   }
  389.  
  390.   m = (Menu*) malloc(sizeof(Menu));
  391.   m->parent = parent;
  392.   getNextLine(buf, MENU_BUFSIZE, f);
  393.   sscanf(buf, "%d ", &(m->nEntries));
  394.  
  395.   getNextLine(buf, MENU_BUFSIZE, f);
  396.   /* TODO: this is horribly broken, 31 is probably wrong
  397.      anyway, so handle arbitrary strings or use magic enums */
  398.   buf[31] = 0; /* enforce menu name limit; */
  399.   sprintf(m->szName, "%s", buf);
  400.   if(*(m->szName + strlen(m->szName) - 1) == '\n')
  401.     *(m->szName + strlen(m->szName) - 1) = 0;
  402.   
  403.   getNextLine(buf, MENU_BUFSIZE, f);
  404.   buf[31] = 0; /* enforce menu caption limit; */
  405.   sprintf(m->szCapFormat, "%s", buf);
  406.   /* remove newline */
  407.   for(i = 0; *(m->szCapFormat + i) != 0; i++)
  408.     if (*(m->szCapFormat + i) == '\n') {
  409.       *(m->szCapFormat + i) = 0;
  410.       break;
  411.     }
  412.  
  413.   initMenuCaption(m);
  414.     
  415.   /* printf("menu '%s': %d entries\n", m->szName, m->nEntries); */
  416.   if(m->nEntries > 0) { /* contains a submenu */
  417.     m->pEntries = malloc(sizeof(Menu*) * m->nEntries);
  418.     for(i = 0; i < m->nEntries; i++) { /* load these sub menus */
  419.       /* printf("loading menu number %d\n", i); */
  420.       if(i > 10) {
  421.     printf("item limit reached - aborting\n");
  422.     exit(1);
  423.       }
  424.       *(m->pEntries + i) = loadMenu(f, buf, m, level + 1);
  425.     }
  426.   }
  427.  
  428.   return m;
  429. }
  430.  
  431. Menu** loadMenuFile(char *filename) {
  432.   char buf[MENU_BUFSIZE];
  433.   FILE* f;
  434.   Menu* m;
  435.   Menu** list = NULL;
  436.   int nMenus;
  437.   int i, j;
  438.   node *head;
  439.   node *t;
  440.   node *z;
  441.   int sp = 0;
  442.  
  443.   if((f = fopen(filename, "r")) == NULL)
  444.     return NULL;
  445.   /* read count of Menus */
  446.   getNextLine(buf, MENU_BUFSIZE, f);
  447.   sscanf(buf, "%d ", &nMenus);
  448.   if(nMenus <= 0) return NULL;
  449.  
  450.   /* allocate space for data structures */
  451.   list = (Menu**) malloc(sizeof(Menu*) * nMenus);
  452.  
  453.   /* load data */
  454.   for(i = 0; i < nMenus; i++) {
  455.     /* printf("loading menu set %d\n", i); */
  456.     /* TODO: bad magic */
  457.     if(i > 10) exit(1);
  458.     *(list + i) = loadMenu(f, buf, NULL, 0);
  459.   }
  460.   fclose(f);
  461.  
  462.   /* TODO(3): now since I eliminated the need for cx/cy, why */
  463.   /* do I need to traverse the Menu Tree? Just to set the colors??? */
  464.  
  465.   /* traverse Menu Tree and set Menu Color to some boring default */
  466.   /* printf("finished parsing file - now traversing menus\n"); */
  467.   /* setup stack */
  468.  
  469.   z = (node*) malloc(sizeof(node));
  470.   z->next = z;
  471.   head = (node*) malloc(sizeof(node));
  472.   head->next = z;
  473.   
  474.   for(i = 0; i < nMenus; i++) {
  475.     t = (node*) malloc(sizeof(node));
  476.     t->data = *(list + i);
  477.     t->next = head->next;
  478.     head->next = t;
  479.     sp++;
  480.     while(head->next != z) {
  481.       t = head->next;
  482.       head->next = t->next;
  483.       m = (Menu*) t->data;
  484.       free(t);
  485.       /* printf("stack count: %d\n", --sp); */
  486.       /* printf("visiting %s\n", m->szName); */
  487.       /* visit m */
  488.  
  489.       /* copy default colors into menu entry */
  490.  
  491.       memcpy(m->display.fgColor, menu_fgColor, sizeof(menu_fgColor) );
  492.       memcpy(m->display.hlColor1, menu_hlColor1, sizeof(menu_hlColor1) );
  493.       memcpy(m->display.hlColor2, menu_hlColor2, sizeof(menu_hlColor2) );
  494.  
  495.       /* push all of m's submenus */
  496.       for(j = 0; j < m->nEntries; j++) {
  497.     t = (node*) malloc(sizeof(node));
  498.     t->data = *(m->pEntries + j);
  499.     t->next = head->next;
  500.     head->next = t;
  501.     /* printf("pushing %s\n", ((Menu*)t->data)->szName); */
  502.     /* printf("stack count: %d\n", ++sp); */
  503.     
  504.       }
  505.     }
  506.   }
  507.   return list;
  508. }
  509.  
  510. void drawMenu(gDisplay *d) {
  511.   /* draw Menu pCurrent */
  512.  
  513.   int i;
  514.   int x, y, size, lineheight;
  515.   int hsize, vsize;
  516.   int maxw = 0;
  517.  
  518.   rasonly(d);
  519.  
  520. #define MENU_TEXT_START_X 0.08
  521. #define MENU_TEXT_START_Y 0.40
  522.  
  523. #define MENU_WIDTH 0.80
  524. #define MENU_HEIGHT 0.40
  525.  
  526. #define MENU_TEXT_LINEHEIGHT 1.5
  527.  
  528.   x = (int) (d->vp_w * MENU_TEXT_START_X);
  529.   y = (int) (d->vp_h * MENU_TEXT_START_Y);
  530.  
  531.   /* new stuff: calculate menu dimensions */
  532.   for(i = 0; i < pCurrent->nEntries; i++) {
  533.     int len;
  534.     len =  strlen(((Menu*)*(pCurrent->pEntries + i))->display.szCaption);
  535.     if(len > maxw)
  536.       maxw = len;
  537.   }
  538.   /* adjust size so menu fits into MENU_WIDTH/HEIGHT */
  539.  
  540.   hsize = (int) ((float)d->vp_w * MENU_WIDTH / (float)maxw );
  541.   vsize = (int) ((float)d->vp_h * MENU_HEIGHT / 
  542.          ( (float)pCurrent->nEntries * MENU_TEXT_LINEHEIGHT));
  543.  
  544.   size = (hsize < vsize) ? hsize : vsize;
  545.  
  546.   lineheight = (int)( (float) size * MENU_TEXT_LINEHEIGHT);  
  547.  
  548.   /* printf("%d %d %d %d %d\n", x, y, size, maxw, pCurrent->nEntries); */
  549.   /* draw the entries */
  550.  
  551.   glEnable(GL_BLEND);
  552.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  553.   for(i = 0; i < pCurrent->nEntries; i++) {
  554.     if(i == pCurrent->iHighlight) {
  555.       // glColor4fv(pCurrent->display.hlColor);
  556.       float color[4];
  557.       int j;
  558.       float t;
  559.       int time = (SystemGetElapsedTime() - menutime) & 4095; 
  560.       t = sin( time * M_PI / 2048.0 ) / 2.0 + 0.5;
  561.       for(j = 0; j < 4; j++) {
  562.     color[j] = 
  563.       t * pCurrent->display.hlColor1[j] + 
  564.       (1 - t) * pCurrent->display.hlColor2[j];
  565.       }
  566.       glColor4fv(color);
  567.     } else 
  568.       glColor4fv(pCurrent->display.fgColor);
  569.  
  570.     drawText(guiFtx, x, y, size,
  571.          ((Menu*)*(pCurrent->pEntries + i))->display.szCaption);
  572.  
  573.     if(i == pCurrent->iHighlight) 
  574.       drawSoftwareHighlight(x, y, size, ((Menu*)*(pCurrent->pEntries + i))->display.szCaption);
  575.  
  576.     y -= lineheight;
  577.   }
  578.   
  579.   glDisable(GL_BLEND);
  580. }
  581.